From 88267ccbbf47b8ecf7ac081874cc31b347e53412 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 26 Nov 2010 14:23:31 +0000 Subject: [PATCH] xenpaging: handle temporary out-of-memory conditions during page-in p2m_mem_paging_prep() should return -ENOMEM if a new page could not be allocated. This can be handled in xenpaging to retry the page-in. Right now such condition would stall the guest because the requested page will not come back, xenpaging simply exits. So xenpaging could very well retry the allocation forever to rescue the guest. Signed-off-by: Olaf Hering --- tools/xenpaging/xenpaging.c | 27 ++++++++++++++++++++------- xen/arch/x86/mm/p2m.c | 2 +- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/tools/xenpaging/xenpaging.c b/tools/xenpaging/xenpaging.c index 136f075aa8..1002661205 100644 --- a/tools/xenpaging/xenpaging.c +++ b/tools/xenpaging/xenpaging.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -415,19 +416,31 @@ static int xenpaging_populate_page( unsigned long _gfn; void *page; int ret; + unsigned char oom = 0; - /* Tell Xen to allocate a page for the domain */ - ret = xc_mem_paging_prep(paging->xc_handle, paging->mem_event.domain_id, - *gfn); - if ( ret != 0 ) + _gfn = *gfn; + do { - ERROR("Error preparing for page in"); - goto out_map; + /* Tell Xen to allocate a page for the domain */ + ret = xc_mem_paging_prep(paging->xc_handle, paging->mem_event.domain_id, + _gfn); + if ( ret != 0 ) + { + if ( errno == ENOMEM ) + { + if ( oom++ == 0 ) + DPRINTF("ENOMEM while preparing gfn %lx\n", _gfn); + sleep(1); + continue; + } + ERROR("Error preparing for page in"); + goto out_map; + } } + while ( ret && !interrupted ); /* Map page */ ret = -EFAULT; - _gfn = *gfn; page = xc_map_foreign_pages(paging->xc_handle, paging->mem_event.domain_id, PROT_READ | PROT_WRITE, &_gfn, 1); *gfn = _gfn; diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index 9620866ef3..d18b3876ae 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -2802,7 +2802,7 @@ int p2m_mem_paging_prep(struct p2m_domain *p2m, unsigned long gfn) /* Get a free page */ page = alloc_domheap_page(p2m->domain, 0); if ( unlikely(page == NULL) ) - return -EINVAL; + return -ENOMEM; /* Fix p2m mapping */ p2m_lock(p2m); -- 2.30.2